# -*- coding: utf-8 -*-
"""
Created on Thu Jan  4 11:39:36 2018

@author:Devin

"""
from collections import Counter
from tqdm import tqdm
import pandas as pd
import numpy as np

all_col = ['tboxid', 'vin', 'starttime', 'gnsstime', 'gnsslong', 'gnsslat',
       'gnssalt', 'gnsshead', 'gnsssats', 'vehspeed', 'vehrpm', 'vehsyspwrmod',
       'vehgearpos', 'tboxaccelx', 'tboxaccely', 'tboxaccelz', 'vehaccelpos',
       'vehbrakepos', 'vehsteeringangle', 'vehfuelconsumed', 'vehdoorfrontpas',
       'vehdoorfrontdrv', 'vehdoorrearleft', 'vehdoorrearright', 'vehbonnet',
       'vehboot', 'vehwindowfrontleft', 'vehwindowrearleft',
       'vehwindowfrontright', 'vehwindowrearright', 'vehsunroof',
       'vehcruiseactive', 'vehcruiseenabled', 'vehcruisetargetspeed',
       'vehoutsidetemp', 'vehinsidetemp', 'vehac', 'vehacauto',
       'vehaccircdirection', 'vehaccirctype', 'vehacfanspeed',
       'vehacdrvtargettemp', 'vehacpasstargettemp', 'vehseatbeltdrv',
       'vehseatbeltpas', 'vehindlightleft', 'vehindlightright', 'vehsidelight',
       'vehdiplight', 'vehmainlight', 'vehfoglightfront', 'vehfoglightrear',
       'vehwiperswitchfront', 'vehraindetected', 'vehnightdetected',
       'vehfuellev', 'vehbatt', 'vehcoolanttemp', 'vehodo', 'vehdistrollcount',
       'vehhorn', 'vehoilpressurewarning', 'vehmilwarning',
       'vehdrivebywirewarning', 'cellmcc', 'cellmnc', 'cellsignalstrength',
       'cellrat', 'celllac', 'cellcellid', 'cellchanid', 'hdop', 'gpsstatus',
       'partnumber', 'version', 'engineering_model', 'rt_minute_pt',
       'createtime', 'sub_engineering_model', 'c_30_dtcinfomationtcm',
       'c_30_dtcinfomationecm', 'c_30_dtcinfomationbcm', 'pt', 'model']

all_cols = ['vin', 'starttime', 'vehspeed', 'vehrpm', 'vehsyspwrmod',
       'vehgearpos', 'tboxaccelx', 'tboxaccely', 'tboxaccelz', 
       'vehbrakepos','vehfuelconsumed',
       'vehoutsidetemp', 'vehinsidetemp', 'vehac', 'vehacauto', 'vehacfanspeed',
       'vehacdrvtargettemp', 'vehacpasstargettemp','vehsidelight',
       'vehdiplight', 'vehmainlight',
       'vehwiperswitchfront',
       'vehfuellev', 'vehbatt', 'vehcoolanttemp', 'vehodo']



#globals()['takes'] = pd.read_csv(path+file_tbox[0], sep=',',usecols = all_cols)

#gc.collect()

class Construction_data():
    '''
    the class of converge of data, default time is day!
    two args need give : df and time
    for df need have common vin at serial time.
    time can give : 'M'/'D'/'H'
    return 42 columns data in every VIN
    
    '''
    
    def __init__(self,df,time='D'):
        self.n_power_time = 'n_power_time'
        self.run_time_2k = 'run_time_2k'
        self.num_non_p = 'num_non_p'
        self.battery_start = 'battery_start'
        self.battery_avg = 'battery_avg'
        self.battery_var = 'battery_var'
        self.battery_max = 'battery_max'
        self.battery_mix4 = 'battery_mix4'
        self.battery_mix1 = 'battery_mix1'
        self.battery_min = 'battery_min'
        self.kurt_v_battery = 'kurt_v_battery'
        self.skew_v_battery = 'skew_v_battery'
        self.avg_temperature_in = 'avg_temperature_in'
        self.avg_temperature_out = 'avg_temperature_out'
        self.starting_num_day = 'starting_num_day'
        self.minutes15_st = '15_minutes_st'
        self.remote_boot_times = 'remote_boot_times'
        self.x_acc = 'x_acc'
        self.y_acc = 'y_acc'
        self.z_acc = 'z_acc'
#        self.accepos_var = 'accepos_var'
        self.brakepos_var = 'brakepos_var'
        self.dr_avg_v = 'dr_avg_v'
        self.dr_avg_mile = 'dr_avg_mile'
#        self.day_fuel = 'day_fuel'
        self.dr_mile50 = 'dr_mile50'
        self.dr_v0_rate = 'dr_v0_rate'
        self.avg_run_mile = 'avg_run_mile'
        self.avg_run_times = 'avg_run_times'
        self.ac_on_count = 'ac_on_count'
        self.ac_auto_on_count = 'ac_auto_on_count'
        self.fanspeed_avg = 'fanspeed_avg'
        self.fanspeed_var = 'fanspeed_var'
        self.d_temp_avg = 'd_temp_avg'
        self.c_temp_avg = 'c_temp_avg'
        self.side_light_count = 'side_light_count'
        self.dip_light_count = 'dip_light_count'
        self.main_light_count = 'main_light_count'
        self.wiperswitch_avg = 'wiperswitch_avg'
        self.oli_box_avg = 'oli_box_avg'
        self.cool_avg = 'cool_avg'
        self.batt_1 = 'batt_1'
        self.batt_0 = 'batt_0'
        self.mils = 'mils'

        
        self.df = df
        self.time = time
        
        self.df.starttime = pd.to_datetime(self.df.starttime)
        self.df.index = self.df.starttime
        self.df = self.df.sort_index()
        
        self.day_index = self.df.to_period(self.time)
        self.day_group = self.day_index.groupby(self.day_index.index)
        
        
    def n_p_time(self,g_df):
        vehsyspwrmod_list = list(g_df.loc[:,'vehsyspwrmod'])
        values_counts = Counter(vehsyspwrmod_list)
        return (values_counts[0]+values_counts[1])/len(vehsyspwrmod_list)
    
    def run_t_2k(self,g_df):
        vehrpm_2k = len(list(g_df[g_df.vehrpm < 2000].loc[:,'vehrpm']))
        return vehrpm_2k/len(list(g_df.loc[:,'vehrpm']))
        
    def num_n_p(self,g_df):
        ttx = np.array(g_df.starttime)
        c = list(np.diff(ttx)/np.timedelta64(1, 's'))
        c.insert(0,1);g_df.loc[:,'temp'] = c
        start_t = g_df[g_df.temp > 10].starttime.tolist()
        i=0
        if len(start_t) == 0:
            return 0
        for t in start_t:
            diff = float(g_df[g_df.starttime==t].iloc[-1].vehbatt)- float(g_df[g_df.starttime<t].iloc[-1].vehbatt)
            i+=diff
            pass
        return i/len(start_t)
    
    def batt_start(self,g_df):
        ttx = np.array(g_df.starttime)
        c = list(np.diff(ttx)/np.timedelta64(1, 's'))
        c.insert(0,1);g_df.loc[:,'temp'] = c
        start_t = g_df[g_df.temp > 10].starttime.tolist()
        i=0
        if len(start_t) == 0:
            return 0
        for t in start_t:
            diff = float(g_df[g_df.starttime==t].iloc[-1].vehbatt)
            i+=diff
            pass
        return i/len(start_t)
    
    def batt_avg(self,g_df):
        return g_df.vehbatt.mean()
        
    
    def batt_var(self,g_df):
        return g_df.vehbatt.std()
    
    def batt_max(self,g_df):
        return g_df.vehbatt.max()
    
    def batt_mix4(self,g_df):
        return g_df.vehbatt.quantile(0.4)   
    
    def batt_mix1(self,g_df):
        return g_df.vehbatt.quantile(0.1) 
    
    def batt_min(self,g_df):
        return g_df.vehbatt.min() 
    
    def kurt_v_batterys(self,g_df):
        return g_df.vehbatt.kurt()
    
    def skew_v_batterys(self,g_df):
        return g_df.vehbatt.skew()
    
    def avg_temp_in(self,g_df):
        return g_df.vehinsidetemp.mean()
    
    def avg_temp_out(self,g_df):
        return g_df.vehoutsidetemp.mean()
        
    def start_num_day(self,g_df):
        ttx = np.array(g_df.starttime)
        c = list(np.diff(ttx)/np.timedelta64(1, 's'))
        c.insert(0,1);g_df.loc[:,'temp'] = c
        return len(g_df[g_df.temp > 10].starttime.tolist())
    
    def min15_st(self,g_df):
        ttx = np.array(g_df.starttime)
        c = list(np.diff(ttx)/np.timedelta64(1, 's'))
        c.insert(0,1);g_df.loc[:,'temp'] = c
        start_t = g_df[g_df.temp > 10].starttime.tolist()
        i=0
        ax = pd.DataFrame(start_t,columns=['t'])
        tc = [x.total_seconds()/60 for x in ax.diff().dropna().t]
        for t in tc:
            if t < 10:
                i+=1
        return i
        
    def remote_times(self,g_df):
        return g_df.vehbatt.median()
    
    def x_ac(self,g_df):
        return g_df.tboxaccelx.std()
    
    def y_ac(self,g_df):
        return g_df.tboxaccely.std()
    
    def z_ac(self,g_df):
        return g_df.tboxaccelz.std()
        
#    def acc_var(self,g_df):
#        pass########################################
#    
    def brak_var(self,g_df):
        return g_df.vehbrakepos.std()
        
    def d_avg_v(self,g_df):
        g_1 = g_df[g_df.vehspeed>0]
        return g_1.vehspeed.mean()
    
    def d_avg_mile(self,g_df):
        return g_df.vehodo.iloc[-1]-g_df.vehodo.iloc[0]
    
#    def days_fuel(self,g_df):
#        pass########################################
    
    def dr_miles50(self,g_df):
        g_1 = g_df[g_df.vehspeed>0]
        return g_1[g_1.vehspeed<50].shape[0]/3600
    
    def dr_v0_rates(self,g_df):
        g_1 = g_df[g_df.vehspeed>0]
        if g_1.shape[0]==0:
            return 0
        return g_1[g_1.vehspeed<50].shape[0]/g_1.shape[0]
    
#    def avg_run_mile(self,g_df):
#        pass########################################
    
    def avg_run_time(self,g_df):
        return g_df[g_df.vehsyspwrmod > 0].shape[0]/3600
        
    def ac_on_counts(self,g_df):
        return g_df[g_df.vehac > 0].shape[0]/g_df.shape[0]
    
    def ac_auto_on_counts(self,g_df):
        return g_df[g_df.vehacauto > 0].shape[0]/g_df.shape[0]
    
    def fanspeed_avgs(self,g_df):
        return g_df.vehacfanspeed.mean()
    
    def fanspeed_vars(self,g_df):
        return g_df.vehacfanspeed.std()
        
    def d_temp_avgs(self,g_df):
        g_p = g_df[g_df.vehacdrvtargettemp>0]
        return g_p.vehacdrvtargettemp.mean()
    
    def c_temp_avgs(self,g_df):
        g_p = g_df[g_df.vehacpasstargettemp>0]
        return g_p.vehacpasstargettemp.mean()
    
    def side_light_counts(self,g_df):
        gs = g_df[g_df.vehsidelight>0]
        return gs.shape[0]/g_df.shape[0]
    
    def dip_light_counts(self,g_df):
        return g_df[g_df.vehdiplight > 0].shape[0]/g_df.shape[0]
    
    def main_light_counts(self,g_df):
        return g_df[g_df.vehmainlight > 0].shape[0]/g_df.shape[0]
    
    def wiperswitch_avgs(self,g_df):
        gs = g_df[g_df.vehwiperswitchfront>0]
        return gs.shape[0]/g_df.shape[0]
    
    def oli_box_avgs(self,g_df):
        return g_df.vehfuellev.mean()
        
    
    def cool_avgs(self,g_df):
        return g_df.vehcoolanttemp.mean()
    
    def milss(self,g_df):
        return g_df.vehodo[-1]
    
    def batt_1s(self,g_df):
        return g_df.vehbatt[-1]
    
    def batt_0s(self,g_df):
        return g_df.vehbatt[0]

    def concat_data(self):
        n_power_time = self.day_group.apply(self.n_p_time).to_frame(name=self.n_power_time)
        run_time_2k =  self.day_group.apply(self.run_t_2k).to_frame(name=self.run_time_2k)
        num_non_p =  self.day_group.apply(self.num_n_p).to_frame(name=self.num_non_p)
        battery_start =  self.day_group.apply(self.batt_start).to_frame(name=self.battery_start)
        battery_avg =  self.day_group.apply(self.batt_avg).to_frame(name=self.battery_avg)
        battery_var =  self.day_group.apply(self.batt_var).to_frame(name=self.battery_var)
        battery_max =  self.day_group.apply(self.batt_max).to_frame(name=self.battery_max)
        battery_mix4 =  self.day_group.apply(self.batt_mix4).to_frame(name=self.battery_mix4)
        battery_mix1 =  self.day_group.apply(self.batt_mix1).to_frame(name=self.battery_mix1)
        battery_min =  self.day_group.apply(self.batt_min).to_frame(name=self.battery_min)
        kurt_v_battery =  self.day_group.apply(self.kurt_v_batterys).to_frame(name=self.kurt_v_battery)
        skew_v_battery =  self.day_group.apply(self.skew_v_batterys).to_frame(name=self.skew_v_battery)
        avg_temperature_in =  self.day_group.apply(self.avg_temp_in).to_frame(name=self.avg_temperature_in)
        avg_temperature_out =  self.day_group.apply(self.avg_temp_out).to_frame(name=self.avg_temperature_out)
        starting_num_day =  self.day_group.apply(self.start_num_day).to_frame(name=self.starting_num_day)
        minutes15_st =  self.day_group.apply(self.min15_st).to_frame(name=self.minutes15_st)
        remote_boot_times =  self.day_group.apply(self.remote_times).to_frame(name=self.remote_boot_times)
        x_acc =  self.day_group.apply(self.x_ac).to_frame(name=self.x_acc)
        y_acc =  self.day_group.apply(self.y_ac).to_frame(name=self.y_acc)
        z_acc =  self.day_group.apply(self.z_ac).to_frame(name=self.z_acc)
#        accepos_var =  self.day_group.apply(self.acc_var).to_frame(name=self.accepos_var)
        brakepos_var =  self.day_group.apply(self.brak_var).to_frame(name=self.brakepos_var)
        dr_avg_v =  self.day_group.apply(self.d_avg_v).to_frame(name=self.dr_avg_v)
        dr_avg_mile =  self.day_group.apply(self.d_avg_mile).to_frame(name=self.dr_avg_mile)
#        day_fuel =  self.day_group.apply(self.days_fuel).to_frame(name=self.day_fuel)
        dr_mile50 =  self.day_group.apply(self.dr_miles50).to_frame(name=self.dr_mile50)
        dr_v0_rate =  self.day_group.apply(self.dr_v0_rates).to_frame(name=self.dr_v0_rate)
#        avg_run_mile =  self.day_group.apply(self.avg_run_miles).to_frame(name=self.avg_run_mile)
        avg_run_times =  self.day_group.apply(self.avg_run_time).to_frame(name=self.avg_run_times)
        ac_on_count =  self.day_group.apply(self.ac_on_counts).to_frame(name=self.ac_on_count)
        ac_auto_on_count =  self.day_group.apply(self.ac_auto_on_counts).to_frame(name=self.ac_auto_on_count)
        fanspeed_avg =  self.day_group.apply(self.fanspeed_avgs).to_frame(name=self.fanspeed_avg)
        fanspeed_var =  self.day_group.apply(self.fanspeed_vars).to_frame(name=self.fanspeed_var)
        d_temp_avg =  self.day_group.apply(self.d_temp_avgs).to_frame(name=self.d_temp_avg)
        c_temp_avg =  self.day_group.apply(self.c_temp_avgs).to_frame(name=self.c_temp_avg)
        side_light_count =  self.day_group.apply(self.side_light_counts).to_frame(name=self.side_light_count)
        dip_light_count =  self.day_group.apply(self.dip_light_counts).to_frame(name=self.dip_light_count)
        main_light_count =  self.day_group.apply(self.main_light_counts).to_frame(name=self.main_light_count)
        wiperswitch_avg =  self.day_group.apply(self.wiperswitch_avgs).to_frame(name=self.wiperswitch_avg)
        oli_box_avg =  self.day_group.apply(self.oli_box_avgs).to_frame(name=self.oli_box_avg)
        cool_avg =  self.day_group.apply(self.cool_avgs).to_frame(name=self.cool_avg)
        mils =  self.day_group.apply(self.milss).to_frame(name=self.mils)
        batt_1 = self.day_group.apply(self.batt_1s).to_frame(name=self.batt_1)
        batt_0 = self.day_group.apply(self.batt_0s).to_frame(name=self.batt_0)
        
        
        vin_data = pd.concat([n_power_time,run_time_2k,num_non_p,battery_start,battery_avg,
                                   battery_var,battery_max,battery_mix4,battery_mix1,battery_min,
                                   kurt_v_battery,skew_v_battery,avg_temperature_in,avg_temperature_out,
                                   starting_num_day,minutes15_st,remote_boot_times,x_acc,y_acc,z_acc,
                                   brakepos_var,dr_avg_v,dr_avg_mile,dr_mile50,dr_v0_rate,
                                   avg_run_times,ac_on_count,ac_auto_on_count,fanspeed_avg,fanspeed_var,
                                   d_temp_avg,c_temp_avg,side_light_count,dip_light_count,main_light_count,wiperswitch_avg,
                                   oli_box_avg,cool_avg,mils,batt_1,batt_0],axis=1)
        vin_data = vin_data.fillna(method='pad');vin_data = vin_data.fillna(method='bfill');vin_data = vin_data.sort_index()
        return vin_data




